package team.archai.nexus.boot.web.shiro.config;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import team.archai.nexus.boot.auth.constant.AuthConstant;
import team.archai.nexus.boot.config.AuthProperties;
import team.archai.nexus.boot.web.filters.ArchaiNexusWebFilter;
import team.archai.nexus.boot.web.shiro.realm.ArchaiNexusRealm;

import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.*;

/**
 * @Description: 基于shiro的权限配置
 * @Author: lishibin
 * @Date: 7/11/2020
 */
@Configuration
@ConditionalOnProperty(name = "archai-nexus.auth.type", havingValue = "shiro")
public class AuthConfig {

    @Resource
    private ArchaiNexusRealm archaiNexusRealm;

    @Resource
    private AuthProperties authProperties;

    @Bean
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl(authProperties.getLoginUrl());
        shiroFilterFactoryBean.setSuccessUrl(authProperties.getSuccessUrl());
        shiroFilterFactoryBean.setUnauthorizedUrl(authProperties.getUnauthorizedUrl());
        LinkedHashMap<String, String> authChain = authProperties.getDefaultFilterChain();
        LinkedHashMap<String, String> filterChain = Optional.ofNullable(authProperties.getFilterChain()).orElse(new LinkedHashMap<>());
        authChain.putAll(filterChain);
        Map<String, Filter> filterMap = new HashMap<>(1);
        filterMap.put(AuthConstant.AUTH_ARCHAI_NEXUS, new ArchaiNexusWebFilter());
        shiroFilterFactoryBean.setFilters(filterMap);
        if (authProperties.isGlobalAuth()) {
            authChain.put("/**", AuthConstant.AUTH_ARCHAI_NEXUS);
        }
        shiroFilterFactoryBean.setFilterChainDefinitionMap(authChain);
        return shiroFilterFactoryBean;
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(archaiNexusRealm);
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }


    /**
     * 开启shiro aop注解支持.
     * 使用代理方式;所以需要开启代码支持;
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }


    /**
     * shiro session的管理
     */
    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//        sessionManager.setGlobalSessionTimeout(tomcatTimeout * 1000);
//        sessionManager.setSessionDAO(sessionDAO());
        Collection<SessionListener> listeners = new ArrayList<SessionListener>();
//        listeners.add(new BDSessionListener());
        sessionManager.setSessionListeners(listeners);
        return sessionManager;
    }

}
